/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
 */
package td.client.presenter;

import td.client.ClientState;
import td.client.event.ThinkerLoginEvent;
import td.client.event.ThinkerLoginEvent.ThinkerLoginHandler;
import td.client.presenter.handlers.RootUiHandlers;
import td.domain.Category;
import td.domain.DemoStore;
import td.domain.StatisticalGrouping;
import td.pt.CategoryPresenter;
import td.pt.LeftNavigationPresenter;
import td.pt.RightNavigationPresenter;
import td.pt.ThinkerPresenter;
import td.pt.event.EditEvent;
import td.pt.event.EditEvent.EditHandler;
import td.pt.event.ThoughtListingEvent;
import td.pt.event.ThoughtListingEvent.ThoughtListingHandler;
import td.pt.widget.SurveyPresenter;
import td.shared.Constants.MAIN;
import td.shared.action.LogoutAction;
import td.shared.action.result.LogoutResult;

import com.google.gwt.event.shared.GwtEvent.Type;
import com.gwtplatform.mvp.client.proxy.RevealContentHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.dispatch.shared.DispatchAsync;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.annotations.ContentSlot;
import com.gwtplatform.mvp.client.annotations.ProxyStandard;
import com.gwtplatform.mvp.client.proxy.Proxy;
import com.gwtplatform.mvp.client.proxy.RevealRootLayoutContentEvent;
import com.gwtplatform.mvp.client.proxy.RevealRootPopupContentEvent;

/**
 * @author Artem Shamsutdinov
 * 
 */
@Singleton
public class RootPresenter extends
		Presenter<RootUiHandlers.MyView, RootPresenter.MyProxy> implements
		RootUiHandlers, ThoughtListingHandler<StatisticalGrouping>,
		ThinkerLoginHandler, EditHandler {

	@ContentSlot
	public static final Type<RevealContentHandler<?>> SLOT_leftNavigation = new Type<RevealContentHandler<?>>();
	@ContentSlot
	public static final Type<RevealContentHandler<?>> SLOT_content = new Type<RevealContentHandler<?>>();
	@ContentSlot
	public static final Type<RevealContentHandler<?>> SLOT_rightNavigation = new Type<RevealContentHandler<?>>();

	@ProxyStandard
	public interface MyProxy extends Proxy<RootPresenter> {
	}

	@Inject
	WaitPresenter waitPresenter;

	@Inject
	LoginJoinPresenter loginJoinPresenter;

	@Inject
	ErrorPresenter errorPresenter;

	@Inject
	DispatchAsync dispatchAsync;

	@Inject
	LeftNavigationPresenter leftNavigationPresenter;

	@Inject
	RightNavigationPresenter rightNavigationPresenter;

	@Inject
	EditPresenter editPresenter;

	@Inject
	ThoughtListingPresenter listingPresenter;

	@Inject
	SurveyPresenter surveyPresenter;

	@Inject
	CategoryPresenter categoryPresenter;

	@Inject
	ThinkerPresenter thinkerPresenter;

	@Inject
	ClientState state;

	@Inject
	public RootPresenter(final EventBus eventBus, final MyView view,
			final MyProxy proxy) {
		super(eventBus, view, proxy);
		view.setUiHandlers(this);
	}

	@Override
	protected void revealInParent() {
		RevealRootLayoutContentEvent.fire(this, this);
	}

	@Override
	protected void onBind() {
		super.onBind();
		// TODO: These seem to be necessary (can't setInSlot from the child
		// presenters)
		registerHandler(getEventBus().addHandler(ThinkerLoginEvent.TYPE, this));
		registerHandler(getEventBus().addHandler(EditEvent.TYPE, this));
		registerHandler(getEventBus()
				.addHandler(ThoughtListingEvent.TYPE, this));

		getView().getSearchButton().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				RevealRootPopupContentEvent.fire(RootPresenter.this,
						waitPresenter);
				Category searchResults = DemoStore.db().searchThoughts(
						getView().getSearchText().getText());
				ThoughtListingEvent<Category> newCategoryListingEvent = new ThoughtListingEvent<Category>(
						"Search results for '"
								+ getView().getSearchText().getText() + "'",
						searchResults);
				leftNavigationPresenter.hideEditControls();
				getEventBus().fireEvent(newCategoryListingEvent);
				waitPresenter.hide();
			}
		});
		getView().getSurveyButton().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				surveyPresenter.getView().show();
			}
		});
		getView().getLoginJoinButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				RevealRootPopupContentEvent.fire(RootPresenter.this,
						loginJoinPresenter);
			}
		});
		getView().getLogoutButton().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				getView().getGreetingLabel().setText(MAIN.HELLO_READER);
				getView().getLoginJoinButton().setVisible(true);
				getView().getLogoutButton().setVisible(false);
				state.setThinker(null);
				state.setThinkerId(null);
				rightNavigationPresenter.onLogout();
			}
		});
	}

	@Override
	protected void onReveal() {
		super.onReveal();
		setInSlot(RootPresenter.SLOT_leftNavigation, leftNavigationPresenter);
		setInSlot(RootPresenter.SLOT_rightNavigation, rightNavigationPresenter);
		DOM.setStyleAttribute(DOM.getElementById("td-loading"), "display",
				"none");
	}

	AsyncCallback<LogoutResult> logoutCallback = new AsyncCallback<LogoutResult>() {

		@Override
		public void onFailure(Throwable caught) {
			RevealRootPopupContentEvent
					.fire(RootPresenter.this, errorPresenter);
			errorPresenter.onError(caught.getMessage());
			waitPresenter.hide();
		}

		@Override
		public void onSuccess(LogoutResult result) {
			getView().onLogout();
			waitPresenter.hide();
		}

	};

	@Override
	public void presentLoginDialog() {
		RevealRootPopupContentEvent.fire(this, loginJoinPresenter);
	}

	@Override
	public void doLogout() {
		// addToPopupSlot(waitPresenter);
		RevealRootPopupContentEvent.fire(this, waitPresenter);
		LogoutAction logoutAction = new LogoutAction();
		dispatchAsync.execute(logoutAction, logoutCallback);
	}

	@Override
	public void onNewGroupingListing(
			ThoughtListingEvent<StatisticalGrouping> event) {
		setInSlot(RootPresenter.SLOT_content, listingPresenter);
	}

	@Override
	public void onThinkerLogin(final ThinkerLoginEvent event) {
		String text = MAIN.PREFIX_HELLO + event.getThinkerId();
		if (event.getJoining()) {
			text = MAIN.PREFIX_WELCOME + event.getThinkerId() + "!";
		}
		getView().getGreetingLabel().setText(text);
		getView().getLoginJoinButton().setVisible(false);
		getView().getLogoutButton().setVisible(true);
		rightNavigationPresenter.onLogin();
	}

	@Override
	public void onEdit(EditEvent event) {
		setInSlot(RootPresenter.SLOT_content, editPresenter);
	}
}
